# 高通QSDK qcawifi源码日志跟踪 ``` ieee80211_assoc_private.h 中有关于状态机的变迁说明 # disassoc 流程分析 首先是状态机 ieee80211_state_info ieee80211_assoc_sm_info[] = { { (u_int8_t) IEEE80211_ASSOC_STATE_DISASSOC, // 状态id (u_int8_t) IEEE80211_HSM_STATE_NONE, //sub 状态 (u_int8_t) IEEE80211_HSM_STATE_NONE, //初始化sbub状态 false, //如果有sub 状态 为true "DISASSOC", //名字 ieee80211_assoc_state_disassoc_entry, //进入时候的action ieee80211_assoc_state_disassoc_exit, //出来时候的action ieee80211_assoc_state_disassoc_event //事件处理函数 }, }; 状态机 { (u_int8_t) IEEE80211_ASSOC_STATE_RUN, (u_int8_t) IEEE80211_HSM_STATE_NONE, (u_int8_t) IEEE80211_HSM_STATE_NONE, false, "RUN", ieee80211_assoc_state_run_entry, ieee80211_assoc_state_run_exit, ieee80211_assoc_state_run_event }, ieee80211_assoc_state_assoc_event //收到事件后 改变状态机为 IEEE80211_ASSOC_STATE_RUN case IEEE80211_ASSOC_EVENT_ASSOC_SUCCESS ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_RUN); 上面的状态机会调用 ieee80211_assoc_state_run_entry { // todo 暂时不知道干嘛 wlan_mlme_connection_up(sm->vap_handle); ieee80211_update_custom_scan_chan_list(sm->vap_handle, true); } ------------------------------------------------------------------------ wlan_assoc_sm_stop { if (flags & IEEE80211_ASSOC_SM_STOP_DISASSOC) { // 发送 IEEE80211_ASSOC_EVENT_DISASSOC_REQUEST 事件 ieee80211_sm_dispatch(smhandle->hsm_handle,IEEE80211_ASSOC_EVENT_DISASSOC_REQUEST,0,NULL); } } 该事件 会触发 函数调用 下面是流程 ieee80211_assoc_state_run_event case IEEE80211_ASSOC_EVENT_DISASSOC_REQUEST // 状态变迁 RUN => DISASSOC ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_DISASSOC); 上面的状态机会调用 ieee80211_assoc_state_disassoc_entry wlan_mlme_disassoc_request_with_callback(tx_disassoc_req_completion) // 注册发送完成回调--》》》等待发送完成 这个里面会发送 disassoc 帧到对端 ……………………………… 省略其他代码 // 在回调函数 tx_disassoc_req_completion { // 发送事件 IEEE80211_ASSOC_EVENT_DISASSOC_SENT ieee80211_sm_dispatch(sm->hsm_handle, IEEE80211_ASSOC_EVENT_DISASSOC_SENT,0,NULL); } 上面的事件发生后会回调下面的函数 ieee80211_assoc_state_disassoc_event case IEEE80211_ASSOC_EVENT_DISASSOC_SENT: case IEEE80211_ASSOC_EVENT_TIMEOUT: // 状态变迁为 DISASSOC => INIT ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); // 转态变为初始化状态 上面的状态变迁会导致下面的exit函数调用 ieee80211_assoc_state_disassoc_exit { 取消定时器等操作 } probe 帧调用流程 mlme_vdev_sta_conn_start_cb ieee80211_mlme_join_infra_continue { ieee80211_send_probereq(ni, vap->iv_myaddr, ni->ni_bssid, ni->ni_bssid, ni->ni_essid, ni->ni_esslen, vap->iv_opt_ie.ie, vap->iv_opt_ie.length); } ieee80211_send_auth 帧的调用流程 ieee80211_assoc_state_join_event case IEEE80211_ASSOC_EVENT_JOIN_SUCCESS: ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_AUTH); ieee80211_assoc_state_auth_event case IEEE80211_ASSOC_EVENT_AUTH_FAIL case IEEE80211_ASSOC_EVENT_TIMEOUT ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_AUTH) case IEEE80211_ASSOC_EVENT_DEAUTH: ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_AUTH) ieee80211_assoc_state_assoc_event case IEEE80211_ASSOC_EVENT_DEAUTH ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_AUTH); 上面的函数收到事件后,触发状态机调用ieee80211_assoc_state_auth_entry static void ieee80211_assoc_state_auth_entry(void *ctx) wlan_mlme_auth_request ieee80211_send_auth(ni, IEEE80211_AUTH_SHARED_REQUEST, 0, NULL, 0, NULL); ``` ``` struct wpa_global * wpa_supplicant_init(struct wpa_params *params) { #ifndef CONFIG_NO_WPA_MSG wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);--------------解释1 #endif /* CONFIG_NO_WPA_MSG */ ret = eap_register_methods();// 注册eap方法 比如MD5 TLS TTLS eloop_init() global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global); // 建立ctrl sockt -g 注册eloop read socket 注册 wpa msg callback 函数 wpas_notify_supplicant_initialized(global)// dbus初始化 hidl初始化 注册hidl read sockt 注册 hidl service vendor HIDL service wifi_display_init(global) eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,wpas_periodic, global, NULL) } 解释1 { wpa_supplicant_init函数的主要功能是初始化wpa_global以及一些与整个程序相关的资源,包括随机数资源、eloop事件循环机制以及设置消息全局回调函数。 此处先简单介绍消息全局回调函数,一共有两个。 wpa_msg_get_ifname_func:有些输出信息中需要打印出网卡接口名。该回调函数用于获取网卡接口名。 wpa_msg_cb_func:除了打印输出信息外,还可通过该回调函数进行一些特殊处理,如把输出信息发送给客户端进行处理。 上述两个回调函数相关的代码如下所示。 wpa_debug.c // wpa_msg_ifname_cb用于获取无线网卡接口名 // WPAS为其设置的实现函数为wpa_supplicant_msg_ifname_cb // 读者可自行阅读此函数 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func){ wpa_msg_ifname_cb = func; } // WPAS中,wpa_msg_cb的实现函数是wpa_supplicant_ctrl_iface_msg_cb,它将输出信息发送给客户端 // 图4-2最后两行的信息就是由此函数发送给客户端的。而且前面的"<3>"也是由它添加的 static wpa_msg_cb_func wpa_msg_cb = NULL; void wpa_msg_register_cb(wpa_msg_cb_func func){ wpa_msg_cb = func; } } wpa_supplicant_ctrl_iface_process{ if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15) { wpa_supplicant_select_network(wpa_s, ssid);---------------------------------- { 127us wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING)---------删除掉接入认证 { 69us wpa_supplicant_clear_connection() { }---------------------------------------------------------------------- } if (wpa_s->connect_without_scan || wpa_supplicant_fast_associate(wpa_s) != 1) {快速链路认证 wpa_s->scan_req = NORMAL_SCAN_REQ; wpas_scan_reset_sched_scan(wpa_s); wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0); log_w("step7\n"); } } }---------------------------------------------------------------------------------------------------------274us } wpa_supplicant_ctrl_iface_roam { wpa_supplicant_connect { wpa_supplicant_req_new_scan { return 0 } wpa_supplicant_associate { wpas_start_assoc_cb { wpas_populate_assoc_ies wpa_drv_associate { wpa_driver_nl80211_associate { wpa_driver_nl80211_connect { wpa_driver_nl80211_try_connect { // wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex); …… ret = send_and_recv_msgs_owner(drv, msg, nl_connect, 1, NULL,(void *) -1, NULL, NULL); // 10ms 左右 …… wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully"); } } } } } } } } void IEEE80211_DPRINTF(struct ieee80211vap *vap, unsigned category, const char *fmt, ...) { #if DBG_LVL_MAC_FILTERING if (!vap->iv_print.dbgLVLmac_on) { #endif va_start(ap, fmt); vsnprintf (tmp,(OS_TEMP_BUF_SIZE - (tmp - tmp_buf)), fmt, ap); va_end(ap); void print_vap_msg(struct ieee80211vap *vap, unsigned category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (vap) { asf_vprint_category(&vap->iv_print, category, fmt, ap); { } } else { qdf_vprint(fmt, ap); { QDF_VTRACE_INFO(QDF_MODULE_ID_ANY, fmt, args); { #ifdef WLAN_LOG_INFO QDF_VTRACE(module_id, QDF_TRACE_LEVEL_INFO, fmt, args) { qdf_vtrace_msg { qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val); { void pr_info(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); } } } } } } va_end(ap); } ic->ic_log_text(ic,tmp_buf); OS_LOG_DBGPRINT("%s\n", tmp_buf); #if DBG_LVL_MAC_FILTERING } #endif } #ifdef QDF_TRACE_PRINT_ENABLE #define qdf_print(args...) QDF_TRACE_INFO(QDF_MODULE_ID_ANY, ## args) #define qdf_alert(args...) QDF_TRACE_FATAL(QDF_MODULE_ID_ANY, ## args) #define qdf_err(args...) QDF_TRACE_ERROR(QDF_MODULE_ID_ANY, ## args) #define qdf_warn(args...) QDF_TRACE_WARN(QDF_MODULE_ID_ANY, ## args) #define qdf_info(args...) QDF_TRACE_INFO(QDF_MODULE_ID_ANY, ## args) #define qdf_debug(args...) QDF_TRACE_DEBUG(QDF_MODULE_ID_ANY, ## args) #ifdef WLAN_LOG_INFO #define QDF_TRACE_INFO(params...) \ __QDF_TRACE_FL(QDF_TRACE_LEVEL_INFO, ## params) #define __QDF_TRACE_FL(log_level, module_id, format, args...) \ QDF_TRACE(module_id, log_level, FL(format), ## args) #if defined(WLAN_DEBUG) || defined(DEBUG) || defined(QDF_TRACE_PRINT_ENABLE) #define QDF_TRACE qdf_trace_msg void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,const char *str_format, ...) { va_list val; va_start(val, str_format); qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val); va_end(val); } qdf_print("[xym debug]qdf_print ieee80211_recv_mgmt\n"); pr_info("[xym debug]pr_info ieee80211_recv_mgmt\n"); printk("[xym debug]printk ieee80211_recv_mgmt\n"); ```